'''
生命游戏。使用分立网格。由于免去了自由运动的agent所需的浮点矩阵运算，因此
速度比连续网格有很大的提升。在本人的计算机上，使用普通的cpython解释器，速度提升的幅度可达70%.
另外，在不启动图形界面时，它对pypy的支持非常好，性能与pypy版的mesa不相上下。

作者：侯展意
协议：木兰2.0
'''

import random
import numpy as np


import takagiabm as tak  # 这是第一种导入的方式。其他示例中还有另一种导入风格，可以按照喜好选用。
def modelSetup(model):
    global density
    for x in range(model.width):
        for y in range(model.height):

            a = (x, y)
            if (random.random() > 1 - density.value / 100.0):  # 将50%的单元格设置为生.其余可自行定义.
                model.grid.getCellByPos(a).setProperty('alive', True)
                model.grid.getCellByPos(a).setColor(tak.red)  # 导入颜色.
            else:
                model.grid.getCellByPos(a).setProperty('alive', False)
                model.grid.getCellByPos(a).setColor(tak.black)  # 设置为黑色.


def countAliveNeighbors(neighbors=[]):  # 在外部定义函数也是可以的！
    count = 0
    for n in neighbors:
        if (n.getTrait('alive') == True):
            count += 1
        else:
            continue
    return count


def cellStep(cell):
    global usegreen

    cell.model.startTiming('getNeighbors')

    neighbors = cell.getNeighbors()  # 获取八个邻居
    cell.model.endTiming('getNeighbors')
    count = countAliveNeighbors(neighbors)
    if (count == 3):

        cell.setTraitLater('alive', True)  # 属性不会立即改变,会等到所有的cell都step完了之后再改变.
    elif (count == 8):
        pass
    elif (count == 2):
        pass
    else:
        cell.setTraitLater('alive', False)

    if (cell.getTrait('alive') == True):
        cell.setColor(tak.red)
    else:
        cell.setColor(tak.black)


density = tak.Var('初始生存细胞密度', 20, range=(0, 1, 100))  # min,max,step，最小，最大和步长。
varList = [density]
tak.DiscreteGridModel = tak.prepareModel(modelClass=tak.DiscreteGridModel, varList=varList,
                                         agentActivationPolicy='none', cellActivationPolicy='casual',
                                         modelInitFunc=modelSetup, width=50, height=50)
tak.DiscreteGridCell = tak.prepareCell(tak.DiscreteGridCell, cellStep)

if __name__ == "__main__":
    tak.simStart(__file__, tak.DiscreteGridModel, noGUI=False, maxSteps=100)  # maxsteps只有在noGUI=True的时候才有效。
    # 图形界面启动时，仿真步数没有限制。
